package at.fhooe.pandora.states;

import at.fhooe.engine.event.events.ControlChangedEvent;
import at.fhooe.engine.event.events.GamePauseEvent;
import at.fhooe.engine.event.events.KeyUpEvent;
import at.fhooe.engine.input.ControlType;
import at.fhooe.engine.mapobject.Wall;
import at.fhooe.engine.pandora.Game;
import at.fhooe.engine.scenegraph.SceneNode;
import at.fhooe.engine.state.State;
import at.fhooe.engine.state.StateDataObject;
import at.fhooe.engine.time.PandoraTimer;
import at.fhooe.pandora.entities.AsteroidEntity;
import at.fhooe.pandora.entities.ShipEntity;
import at.fhooe.pandora.views.PlayView;
import at.fhooe.pandora.visuals.PauseVisual;

public class PlayState implements State, KeyUpEvent.Listener, GamePauseEvent.Listener {

	public static final String NAME = "PlayState";
	public static final String GAME_TIMER = "GameTimer";
	
	private PlayView m_playView;
	private PandoraTimer m_gameTimer;
	private ShipEntity m_shipEntity;
	
	private ControlType m_actualControl = ControlType.AlternativeMouse;
	
	public PlayState() {
		m_playView = new PlayView(0.7, 0.7);
		m_gameTimer = Game.getInstance().getPandoraTimerByName(GAME_TIMER);
		m_gameTimer.setScale(1);	//Slow or speed up Time
	}
	
	public String getName() {
		return NAME;
	}
	
	public void engage() {
		addListeners();
		
		m_playView.engage();
		m_gameTimer.setPaused(false);
		
		// engage entities
		m_shipEntity = new ShipEntity("shipEntity", m_gameTimer.getName());
		m_shipEntity.setPosition(Game.getInstance().getGraphicsSystem().getWidth() / 2.0, Game.getInstance().getGraphicsSystem().getHeight() / 2.0, 0.0);
		Game.getInstance().getEntityManager().addEntity(m_shipEntity);
		
		Wall wall = new Wall("Map_Wall", "wall1", Game.getInstance().getGraphicsSystem().getWidth() / 2.0+100, Game.getInstance().getGraphicsSystem().getHeight() / 2.0, 0);
		Game.getInstance().getPathfindingManager().addMapObject(wall);
		wall = new Wall("Map_Wall", "wall2", Game.getInstance().getGraphicsSystem().getWidth() / 2.0+100, Game.getInstance().getGraphicsSystem().getHeight() / 2.0 +50, 0);
		Game.getInstance().getPathfindingManager().addMapObject(wall);
		wall = new Wall("Map_Wall", "wall3", Game.getInstance().getGraphicsSystem().getWidth() / 2.0+100, Game.getInstance().getGraphicsSystem().getHeight() / 2.0 +100, 0);
		Game.getInstance().getPathfindingManager().addMapObject(wall);
		wall = new Wall("Map_Wall", "wall4", Game.getInstance().getGraphicsSystem().getWidth() / 2.0+100, Game.getInstance().getGraphicsSystem().getHeight() / 2.0 +150, 0);
		Game.getInstance().getPathfindingManager().addMapObject(wall);
		wall = new Wall("Map_Wall", "wall5", Game.getInstance().getGraphicsSystem().getWidth() / 2.0+100, Game.getInstance().getGraphicsSystem().getHeight() / 2.0 +200, 0);
		Game.getInstance().getPathfindingManager().addMapObject(wall);
//		wall = new Wall("Map_Wall", "wall0", 1,1,0);
//		Game.getInstance().getPathfindingManager().addMapObject(wall);
		AsteroidEntity asteroid;
		for(int i = 0; i < 4; i++) {
			// prevent the asteroids of being initialized in the center of the screen
			double asteroidStartPosX = Game.getInstance().getGraphicsSystem().getWidth() / 2.0 + (100 + Math.random() * Game.getInstance().getGraphicsSystem().getWidth() / 4.0); 
			double asteroidStartPosY = Game.getInstance().getGraphicsSystem().getHeight() / 2.0 + (100 + Math.random() * Game.getInstance().getGraphicsSystem().getHeight() / 4.0);
			asteroidStartPosX = Math.random() < 0.5 ? asteroidStartPosX : -asteroidStartPosX;
			asteroidStartPosY = Math.random() < 0.5 ? asteroidStartPosY : -asteroidStartPosY;
			
			asteroid = new AsteroidEntity(	"asteroid" + i,
											m_gameTimer.getName(), 30.0, 
											asteroidStartPosX,
											asteroidStartPosY,
											0.0,
											Math.random() * 50,
											Math.random() * 50,
											0.0);
			Game.getInstance().getEntityManager().addEntity(asteroid);
		}
		//ResourceEntity res = new ResourceEntity("resource", m_gameTimer.getName(), Game.getInstance().getGraphicsSystem().getWidth() / 2.0, Game.getInstance().getGraphicsSystem().getHeight() / 2.0, 0, 0, 0, 0, 1);									
		//Game.getInstance().getEntityManager().addEntity(res);								
	}
	
	public void engage(StateDataObject data) {
		engage();
	}

	public void disengage() {
		removeListeners();
		
		Game.getInstance().getEventManager().clearEventsForDispatch();
		Game.getInstance().getEntityManager().clearEntitiesToEngage();
		Game.getInstance().getEntityManager().removeAllEntities();
		Game.getInstance().getPathfindingManager().removeAllMapObjects();
		
		m_playView.disengage();
	}
	
	private void addListeners() {
		Game.getInstance().getEventManager().addListener(this, KeyUpEvent.TYPE);
		Game.getInstance().getEventManager().addListener(this, GamePauseEvent.TYPE);
	}
	
	private void removeListeners() {
		Game.getInstance().getEventManager().removeListener(this, KeyUpEvent.TYPE);
		Game.getInstance().getEventManager().removeListener(this, GamePauseEvent.TYPE);
	}

	public void onKeyUpEvent(KeyUpEvent keyUpEvent) {
		if(keyUpEvent.getKeyCode() == 27) {	// ESC
			Game.getInstance().getStateManager().switchToState(MenuState.NAME);
			//Game.getInstance().getEventManager().addEvent(new WindowCloseRequestEvent());
		} else if(keyUpEvent.getKeyCode() == 'P') {
			Game.getInstance().getEventManager().dispatchEvent(new GamePauseEvent());
		} else if (keyUpEvent.getKeyCode() == 'O') {
			if (m_actualControl == ControlType.MouseControl) {
				m_actualControl = ControlType.AlternativeMouse;
			} else if (m_actualControl == ControlType.AlternativeMouse) {
				m_actualControl = ControlType.MouseControl;
			} else if (m_actualControl == ControlType.FullKeyboard) {
				m_actualControl = ControlType.MouseControl;
			}
			System.out.println("Control state: "+m_actualControl);
			Game.getInstance().getEventManager().dispatchEvent(new ControlChangedEvent(m_actualControl));
		}
	}

	public void onGamePauseEvent(GamePauseEvent gamePauseEvent) {
		if(!m_gameTimer.isPaused()) {
			m_gameTimer.setPaused(true);
			
			SceneNode node = Game.getInstance().getSceneNodeManager().createSceneNode("Pause");
			if (node != null)
				node.setVisual(new PauseVisual());
		} else {
			m_gameTimer.setPaused(false);
			
			Game.getInstance().getSceneNodeManager().destroySceneNode("Pause");
		}
	}

}
